MENU
Chat App with Web Socket
If you are using a domain name, make sure you forward the port at your modem router appropriately.To maintain a persistent listening socket at the server, you must run the following PHP script in the Windows command line on the computer where PHP is installed. Simply enter ‘PHP –q server.php’ and leave the window open. To run the command automatically in the background, place the command in a batch file and use a service manager such as NSSM, RunAsService, and AlwaysUp.
RESETRUNFULL
<?php
// server.php
$host = 'localhost';
$port = '30000';
$null = NULL; // to be passed by reference
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socket, 0, $port);
socket_listen($socket);
$clients = array($socket);
while (true) {
$changed = $clients;
socket_select($changed, $null, $null, 0, 10);
// check for any new socket
if (in_array($socket, $changed)) {
$socket_new = socket_accept($socket);
$clients[] = $socket_new;
$header = socket_read($socket_new, 1024);
perform_handshaking($header, $socket_new, $host,$port);
socket_getpeername($socket_new, $ip); // the ip address
$response = json_encode(array('type'=>'system','message'=>$ip.' connected'));
send_message($response);
$found_socket = array_search($socket, $changed);
unset($changed[$found_socket]);
}
foreach ($changed as $changed_socket) {
while(socket_recv($changed_socket, $buf, 1024, 0)>=1){
$received_text = unmask($buf);
$tst_msg = json_decode($received_text);
$user_name = $tst_msg->name;
$user_message = $tst_msg->message;
$user_color = $tst_msg->color;
$response_text = json_encode(array('type'=>'usermsg', 'name'=>$user_name,'message'=>$user_message, 'color'=>$user_color));
send_message($response_text);
break 2;
}
// check disconnected client
$buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ);
if ($buf === false) {
$found_socket = array_search($changed_socket, $clients);
socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
$response = json_encode(array('type'=>'system', 'message'=>$ip.' disconnected'));
send_message($response);
}
}
}
socket_close($sock);
// sends a message to all connected clients
function send_message($msg){
global $clients;
$msg = mask($msg);
foreach($clients as $changed_socket)
@socket_write($changed_socket,$msg,strlen($msg));
return true;
}
function unmask($text) {
$length = ord($text[1]) & 127;
if($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
} elseif($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
} else {
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
//Encode message for transfer to client.
function mask($text){
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
function perform_handshaking($receved_header,$client_conn,$host, $port){
$headers = array();
$lines = preg_split("/\r\n/", $receved_header);
foreach($lines as $line){
$line = chop($line);
if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
$headers[$matches[1]] = $matches[2];
}
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/index.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn,$upgrade,strlen($upgrade));
}
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8' />
<script>
var colors = ['007AFF','FF7000','FF7000','15E25F','CFC700','CFC700','CF1100','CF00BE','F00'];
var userColor = colors[Math.floor(Math.random()*10)];
var wsUri = "ws://binarybehemoth.com:30000/server.php";
websocket = new WebSocket(wsUri);
websocket.onopen = function(ev) {
systemMessage('Connected');};
websocket.onerror = function(ev){ systemMessage('Error:'+ev.data);};
websocket.onclose = function(ev){ systemMessage('Connection closed');};
websocket.onmessage = function(ev) {
var msg = JSON.parse(ev.data);
if(msg.type == 'usermsg')
userMessage(msg.name,msg.message,msg.color);
if(msg.type == 'system') systemMessage(msg.message);
document.getElementById('message').value="";
};
function send(){
var mymessage = document.getElementById('message').value;
var myname = document.getElementById('name').value;
if(myname == ""){
alert("Please enter a nickname!");
return;
}
if(mymessage == ""){
alert("Please enter a message!");
return;
}
var msg = { message: mymessage, name: myname, color : userColor };
websocket.send(JSON.stringify(msg));
}
function systemMessage(msg){
document.getElementById('message_box').innerHTML += "<span style='font-size:14px; color: #BDBDBD;"+ "font-style: italic;'>"+msg+"</span><br/>";
}
function userMessage(username, msg, color){
if (String(username)=='null' || String(msg)=='null') return;
document.getElementById('message_box').innerHTML += "<span style='color:#"+color+";'>"+username+":</span>"+ "<span style='color:#88B6E0;'>"+msg+"</span><br/>";
}
</script>
</head>
<body>
<div style="width: 500px; background: #CCCCCC; padding: 10px; border: 1px solid #999999; ">
<div id="message_box" style="background: #FFFFFF; height: 150px; overflow: auto; padding: 10px; border: 1px solid #999999;font-size: 14px;"></div>
<input type="text" id="name" placeholder="Your Name" maxlength="10" style="width:20%" />
<input type="text" id="message" placeholder="Message" maxlength="80" style="width:60%" />
<button onclick="send()">Send</button>
</div>
</body>
</html>